package com.shyroke.daydayzhuansvc.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.shyroke.daydayzhuanapi.constant.CommitConstant;
import com.shyroke.daydayzhuanapi.constant.ProjectConst;
import com.shyroke.daydayzhuanapi.constant.ProjectFromConstant;
import com.shyroke.daydayzhuanapi.constant.RedisKeyPrefix;
import com.shyroke.daydayzhuanapi.dto.*;
import com.shyroke.daydayzhuanapi.entity.*;
import com.shyroke.daydayzhuanapi.enumerated.InviteImgTypeEnum;
import com.shyroke.daydayzhuanapi.enumerated.ProjectLikeDipEnum;
import com.shyroke.daydayzhuanapi.mapper.LabelMapper;
import com.shyroke.daydayzhuanapi.mapper.ProjectMapper;
import com.shyroke.daydayzhuanapi.mapper.TypeMapper;
import com.shyroke.daydayzhuanapi.mapper.UserMapper;
import com.shyroke.daydayzhuandao.respository.*;
import com.shyroke.daydayzhuansvc.manager.ProjectManager;
import com.shyroke.daydayzhuansvc.service.IProjectService;
import com.shyroke.daydayzhuansvc.util.*;
import org.apache.commons.collections.CollectionUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 类名 ：
 * 用法 ：
 * 创建人 ： shyroke
 * 时间：2018/12/28 17:07
 */
@Service
public class ProjectService implements IProjectService {

    @Autowired
    private ProjectRepository projectRepository;
    @Autowired
    private JPAQueryFactory factory;
    @Autowired
    private OSSService ossService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProjectLabelRepository projectLabelRepository;
    @Autowired
    private ProjectEndRepository projectEndRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private LabelRepository labelRepository;
    @Autowired
    private AppService appService;
    @Autowired
    private SpiderImageService spiderImageService;
    @Autowired
    private CopyProjectRepository copyProjectRepository;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ProjectSubjectRepository projectSubjectRepository;
    @Autowired
    private ProjectAppRepository projectAppRepository;
    @Autowired
    private AppRepository appRepository;
    @Autowired
    private ProjectLikeDipRepository projectLikeDipRepository;
    @Autowired
    private TypeRepository typeRepository;
    @Autowired
    private TypeMapper typeMapper;
    @Autowired
    private LabelMapper labelMapper;
    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    private CommitService commitService;
    @Autowired
    private ProjectManager projectManager;
    @Autowired
    private InviteImgRepository inviteImgRepository;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public TabelData<ProjectDto> getNormalProjectList(Page page, ProjectDto pro, UserMain user) {
        Set<RoleEntity> roleList = userRepository.findByName(user.getName()).getRoleList();
        boolean isAdmin = UserUtils.isAdmin2(roleList);

        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        QTypeEntity qTypeEntity = QTypeEntity.typeEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity)
                .leftJoin(qTypeEntity).on(qProjectEntity.typeObj.id.eq(qTypeEntity.id))
                .where(qProjectEntity.type.eq("A"));

        if(StrUtil.isNotBlank(pro.getCommented())){
            query = query.where(qProjectEntity.commented.eq(pro.getCommented()));
        }
        if(pro.getTypeId() != null){
            query = query.where(qProjectEntity.typeObj.id.eq(pro.getTypeId()));
        }
        if(pro.getCreateId() != null){
            query = query.where(qProjectEntity.createId.eq(pro.getCreateId()));
        }
        if(StrUtil.isNotBlank(pro.getCommented())) {
            query.where(qProjectEntity.commented.eq(pro.getCommented()));
        }
        if(pro.getLabelId() != null){
            List<ProjectLabelEntity> list = projectLabelRepository.findByLabelid(Integer.valueOf(pro.getLabelId()));
            if(CollectionUtil.isNotEmpty(list)){
                List<Integer> projectIdList = list.stream().map(e -> e.getProjectid()).collect(Collectors.toList());
                query = query.where(qProjectEntity.id.in(projectIdList));
            }
        }
        if(!isAdmin && user.getId() != null){
            query = query.where(qProjectEntity.createId.eq(user.getId()));
        }
        if(StrUtil.isNotBlank(pro.getTitle())){
            query = query.where(qProjectEntity.title.like("%"+pro.getTitle()+"%"));
        }

        query = query.offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit());

        QueryResults<ProjectEntity> queryResults = null;
        if(pro.getSortField() != null && pro.getSortOrder() != null) {
            if("todayReadCount".equals(pro.getSortField())) {
                if("desc".equals(pro.getSortOrder())) {
                    queryResults = query.orderBy(qProjectEntity.todayReadCount.desc()).fetchResults();
                }else if("asc".equals(pro.getSortOrder())) {
                    queryResults = query.orderBy(qProjectEntity.todayReadCount.asc()).fetchResults();
                }else {
                    queryResults = query.orderBy(qProjectEntity.createTime.desc()).fetchResults();
                }
            }else {
                queryResults = query.orderBy(qProjectEntity.createTime.desc()).fetchResults();
            }
        }else {
            queryResults = query.orderBy(qProjectEntity.createTime.desc()).fetchResults();
        }


//        QueryResults<ProjectEntity> queryResults = query
//                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
//                .orderBy(qProjectEntity.createTime.desc())
//                .fetchResults();

        List<ProjectDto> list = queryResults.getResults().stream().map(e -> {
            ProjectDto dto = projectMapper.entityToDto(e);
            if (!StringUtils.isEmpty(dto.getCover())) {
                dto.setCover(ossService.getImgUrl(dto.getCover()));
            }
            return dto;
        }).collect(Collectors.toList());

        return new TabelData(list,(int)queryResults.getTotal());
    }

    @Override
    @Transactional
    public void deleteById(Integer id) {

        //1.删除该项目的图片,等项目记录删除之后再删除图片，防止删除记录失败后回滚，导致项目记录没删但是图片没了
        Optional<ProjectEntity> optionalProject = projectRepository.findById(id);
        if (!optionalProject.isPresent()) {
            logger.error("id不存在实体，{}",id);
            return;
        }
        ProjectEntity project = optionalProject.get();
        String content = project.getContent();
        String cover = project.getCover();

        List<String> imgSrcList = CommonUtil.getImgSrcList(content);

        //2.保存到copy_project表中
        CopyProjectEntity copyProject = new CopyProjectEntity();
        BeanUtils.copyProperties(project,copyProject);
        copyProjectRepository.save(copyProject);

        //删除项目
        projectRepository.deleteById(id);

        //删除图片
        if(imgSrcList != null && imgSrcList.size()>0){

            for(String img:imgSrcList){
                int index = img.indexOf("?");

                if(index == -1){
                    continue;
                }

                img = img.substring(0,index);
                //取出图片名
                String imgName = img.substring(img.lastIndexOf("/")+1,img.length());
                //将特殊字符转义
                imgName = CommonUtil.decode(imgName);

                try {
                    //删除OSS上的图片
                    ossService.deleteImg(OSSClientConstants.BUCKET_NAME,OSSClientConstants.CONTENT_PATH+CommonUtil.getDateByFormat(new Date(),"yyyy-MM-dd")+"/"+imgName);
                }catch (Exception e){
                    logger.info("图片删除失败，"+ExceptionUtil.getMessage(e));
                }

            }
        }

        if(!StringUtils.isEmpty(cover) && !ProjectConst.DEFAULT_COVER.equals(cover)){ //封面不为空或者不等于默认封面
            //删除封面
            ossService.deleteImg(OSSClientConstants.BUCKET_NAME,cover);
        }
    }

    @Override
    @Transactional
    public Integer save(ProjectDto project) {
        if("1".equals(project.getIsTemp())){
            //草稿，存放到redis
            List<ProjectDto> projectTemList = RedisUtils.readList(RedisKeyPrefix.PROJECTTEMLIST);
            if(projectTemList == null){
                projectTemList = new ArrayList<>();
            }

            projectTemList.add(project);
            redisTemplate.opsForValue().set(RedisKeyPrefix.PROJECTTEMLIST,projectTemList);
            return null;
        }

        if(StringUtils.isEmpty(project.getSource())){
            //如果为空，说明不是变现反馈或者项目进展
            project.setSource(ProjectFromConstant.NORMAL);
        }
        if(!StringUtils.isEmpty(project.getSummary())){
            project.setSummary(project.getSummary().replaceAll("\n",""));
        }

        if(StrUtil.isNotBlank(project.getSummary())) {
            project.setSummary(EmojiUtil.filterEmoji(project.getSummary()));
        }
        ProjectEndEntity projectEnd = this.getProjectEndRandom();
        if(projectEnd!=null){
            project.setContent(project.getContent()+"<p class='project_end'>每日寄语："+projectEnd.getContent()+"</p>");
        }

        //插入邀请二维码，增加nofollow处理
        project.setContent(setInvateImage(project.getContent(),project.getTitle()));
        //插入邀请app
        List<Integer> containAppIdList = new ArrayList<>();
        project.setContent(insertApp(project.getContent(),containAppIdList));

        //1、如果是变现反馈、项目进展文章，直接使用第一张图片作为封面。
        //2、如果不是上述项目，且是薅羊毛项目或者首码项目，使用第二张图片作为封面（通常第一张是邀请码）
        if(org.apache.commons.lang3.StringUtils.isBlank(project.getCover())){
            this.setCoverByTypeAndFrom(project);
        }else{
            project.setCover(CommonUtil.deleteOSSImgPre(project.getCover()));
        }

        //保存普通项目，返回ID
        project.setTypeId(Integer.valueOf(project.getTypes()));
        if(project.getTypeId() != 1 && StrUtil.isBlank(project.getCover())) {

        }
        ProjectEntity projectEntity = projectMapper.dtoToEnTity(project);
        projectRepository.save(projectEntity);
        Integer saveId = projectEntity.getId();

        //保存project-app关联关系
        if(CollectionUtil.isNotEmpty(containAppIdList)){
            containAppIdList.stream().forEach(appId -> {
                ProjectAppEntity relation = new ProjectAppEntity();
                relation.setProjectId(saveId);
                relation.setAppId(appId);
                projectAppRepository.save(relation);
            });
        }

        if(CollectionUtil.isNotEmpty(project.getSubjectIdList())){
            project.getSubjectIdList().stream().forEach(subjectId ->{
                ProjectSubjectEntity projectSubject = new ProjectSubjectEntity();
                projectSubject.setProjectId(saveId);
                projectSubject.setSubjectId(subjectId);
                projectSubjectRepository.save(projectSubject);
            });
        }

        String labels = project.getLabels();
        List<ProjectLabelEntity> projectLabelKeyList = new ArrayList<>();

        if(StringUtils.isEmpty(project.getTypes())){
            throw  new RuntimeException("类型不能为空");
        }

        List<String> labelIdList = new ArrayList<>();
        if(org.apache.commons.lang3.StringUtils.isNotEmpty(labels)){
            String[] labelArr = labels.split(",");
            for(String labelId : labelArr){
                ProjectLabelEntity projectLabelKey = new ProjectLabelEntity();
                projectLabelKey.setLabelid(Integer.valueOf(labelId));
                projectLabelKey.setProjectid(saveId);
                labelIdList.add(labelId);
                projectLabelKeyList.add(projectLabelKey);
            }
        }
        
        //关键词保存到label中
        String keyword = project.getKeyword();
        if(!StringUtils.isEmpty(keyword)){
            String[] split = keyword.split(",");
            for (String key : split) {
                LabelEntity existLabel = labelRepository.findByLabelName(key);
                if(existLabel == null){
                    existLabel = new LabelEntity();
                    existLabel.setIsShowTitle(0);
                    existLabel.setLabelName(key);
                    labelRepository.save(existLabel);

                    ProjectLabelEntity projectLabelKey = new ProjectLabelEntity();
                    projectLabelKey.setLabelid(Integer.valueOf(existLabel.getId()));
                    projectLabelKey.setProjectid(saveId);
                    projectLabelKeyList.add(projectLabelKey);
                }else{
                    if(!labelIdList.contains(existLabel.getId().toString())){
                        ProjectLabelEntity projectLabelKey = new ProjectLabelEntity();
                        projectLabelKey.setLabelid(Integer.valueOf(existLabel.getId()));
                        projectLabelKey.setProjectid(saveId);
                        projectLabelKeyList.add(projectLabelKey);
                    }
                }
            }
        }

        if(CollectionUtils.isNotEmpty(projectLabelKeyList)){
            //批量插入项目_标签表
            projectLabelRepository.saveAll(projectLabelKeyList);
        }

        //删除短语
        if(projectEnd!=null){
            projectEndRepository.deleteById(projectEnd.getId());
        }

        //删除今日可赚
        redisTemplate.delete(RedisKeyPrefix.PROFIT_TODAY);

        //删除置顶文章
        redisTemplate.delete(RedisKeyPrefix.PROJECT_RECOMMENTED);

        //如果是变现反馈、项目进展，显示原文地址
        String source = project.getSource();
        if (!ProjectFromConstant.NORMAL.equals(source)){
            Integer parentId = project.getProjectId();
            Optional<ProjectEntity> optionalProject = projectRepository.findById(parentId);
            if (optionalProject.isPresent()) {
                ProjectEntity parent = optionalProject.get();
                String url = "https://www.daydayzhuan.com/article/"+parent.getId();
                String newContent = "<blockquote>项目攻略：<a  href='"+url+"' title='"+parent.getTitle()+"'>"+parent.getTitle()+"</a></blockquote>";
                String oldContent = project.getContent();
                projectEntity.setContent(newContent+oldContent);
            }

        }

        String url = "https://www.daydayzhuan.com/article/"+saveId;
        String hidenContent = "<a style='color: white!important;'  href='"+url+"' title='天天线报网'>天天线报网</a>";
        String oldContent = project.getContent();
        projectEntity.setContent(oldContent+hidenContent);
        projectRepository.save(projectEntity);

        //记录作者提交记录
        commitRecord(project.getCreateId());

        //提交百度、bing
        if(!"dev".equals(active)){
            projectManager.commitSearch(url);
        }

        return saveId;
    }

    private String insertApp(String content,List<Integer> containAppIdList) {
        Document document = Jsoup.parse(content);
        Elements elements = document.select("p");
        List<AppDto> projectInvateList = appService.findAll();
        Map<String, AppDto> markProjectInvateMap = projectInvateList.stream().filter(dto -> StrUtil.isNotBlank(dto.getTitle())).collect(Collectors.toMap(AppDto::getTitle, AppDto -> AppDto));
        for (Element element : elements) {
            String text = element.text();
            if(text.startsWith("@@")){
                element.text("");
                String appTitle = text.replaceAll("@@","");
                AppDto app = markProjectInvateMap.get(appTitle);
                if(app != null){
                    containAppIdList.add(app.getId());
                    Element div = new Element("div");
                    div.attr("class","layui-row layui-col-md-offset4 relation_app_div relation_div");
                    div.attr("data-id","app-"+app.getId());

                    //封面div
                    Element imgDiv = new Element("div");
                    imgDiv.attr("class","layui-col-md2 layui-col-xs3 back_color relation_app_div");
                    Element img = new Element("img");
                    img.attr("src",ossService.getImgUrl(app.getCover()));
                    img.attr("title",app.getTitle()+"封面图");
                    img.attr("alt",app.getTitle()+"封面图");
                    img.attr("class","tg-list");
                    imgDiv.appendChild(img);
                    div.appendChild(imgDiv);

                    //封面div
                    Element titleDiv = new Element("div");
                    titleDiv.attr("class","layui-col-md2 layui-col-xs4 back_color relation_app_div");
                    Element a = new Element("a");
                    a.attr("href","/app/"+app.getId());
                    a.attr("target","_blank");
                    a.attr("class","cover app_a");
                    a.text(app.getTitle());
                    Element p1 = new Element("p");
                    p1.attr("class","p");
                    p1.text("支持："+app.getShowDevice());
                    Element p2 = new Element("p");
                    p2.attr("class","p");
                    p2.text("下载："+app.getDownCount());
                    titleDiv.appendChild(a);
                    titleDiv.appendChild(p1);
                    titleDiv.appendChild(p2);
                    div.appendChild(titleDiv);

                    //封面div
                    Element infoDiv = new Element("div");
                    infoDiv.attr("class","layui-col-md4 layui-col-xs4 back_color relation_app_div");
                    Element infoa = new Element("a");
                    infoa.attr("class","layui-btn layui-btn-xs app_a");
                    infoa.attr("title",app.getTitle()+"下载");
                    infoa.attr("href","/app/"+app.getId());
                    infoa.attr("target","_blank");
                    infoa.text("下载");
                    Element infoa2 = new Element("a");
                    infoa2.attr("href","/tag/"+app.getFirstLableName());
                    infoa2.attr("target","_blank");
                    infoa2.attr("class","info app_a");
                    infoa2.text(app.getFirstLableName());
                    Element infop = new Element("p");
                    infop.attr("class","publish_p");
                    infop.text("发布："+DateUtil.format(app.getCreateTime(),"yyyy-MM-dd"));
                    infoDiv.appendChild(infoa);
                    infoDiv.appendChild(infoa2);
                    infoDiv.appendChild(infop);
                    div.appendChild(infoDiv);

                    element.appendChild(div);
                }
            }
        }
        return document.html();
    }

    private String setInvateImage(String content,String title) {
        Document document = Jsoup.parse(content);
        Elements elements = document.select("p");
        List<AppDto> projectInvateList = appService.findAll();
        Map<String, AppDto> markProjectInvateMap = projectInvateList.stream().collect(Collectors.toMap(AppDto::getMark, AppDto -> AppDto));
        for (Element element : elements) {
            String text = element.text();
            if(text.startsWith("##")){
                if("##img".equals(text)){
                    SpiderImageEntity spiderImage = spiderImageService.getSpiderImage();
                    if(spiderImage != null){
                        element.text("");
                        element.attr("style","text-align:center;");
                        Element imgEle = new Element("img");
                        imgEle.attr("src",ossService.getImgUrl(spiderImage.getUrl()));
                        imgEle.attr("title",title+"-配图");
                        imgEle.attr("alt",title+"-配图");
                        element.appendChild(imgEle);
                    }
                }else if(text.endsWith("提现")){
                    text = text.replaceAll("提现", "");
                    AppDto app = markProjectInvateMap.get(text);
                    if(app != null){
                        element.text("");
                        element.attr("style","text-align:center;");
                        Element imgEle = new Element("img");
                        imgEle.attr("src",ossService.getImgUrl(app.getWithdraw()));
                        imgEle.attr("data-id",app.getMark().replaceAll("#",""));
                        imgEle.attr("title",app.getTitle()+"提现图");
                        imgEle.attr("alt",app.getTitle()+"提现图");
                        element.appendChild(imgEle);
                    }
                }else{
                    AppDto app = markProjectInvateMap.get(text);
                    if(app != null){
                        element.text("");
                        element.attr("style","text-align:center;");
                        Element imgEle = new Element("img");
                        imgEle.attr("src",ossService.getImgUrl(app.getInviteImg()));
                        imgEle.attr("data-id",app.getMark().replaceAll("#",""));
                        imgEle.attr("title",app.getMark().replaceAll("#","")+"注册图");
                        imgEle.attr("alt",app.getMark().replaceAll("#","")+"注册图");
                        element.appendChild(imgEle);
                    }
                }
            }else if(text.startsWith("%%")) {
                text = text.replaceAll("%%", "");
                InviteImgEntity entity = inviteImgRepository.findTopByImgType(InviteImgTypeEnum.valueOf(text));
                if(entity != null){
                    element.text("");
                    element.attr("style","text-align:center;");
                    Element imgEle = new Element("img");
                    imgEle.attr("src", entity.getUrl());
                    imgEle.attr("width", "200");
                    imgEle.attr("title",title+"-配图");
                    imgEle.attr("alt",title+"-配图");
                    element.appendChild(imgEle);
                }
            }
        }
        Elements aEles = document.select("a");
        if(aEles != null){
            for (Element aEle : aEles) {
                String href = aEle.attr("href");
                if(!href.contains("daydayzhuan.com")){
                    aEle.attr("rel","nofollow");
                }

            }
        }
        Elements imgEles = document.select("img");
        if(imgEles != null){
            for (Element aEle : imgEles) {
                String href = aEle.attr("src");
                if(!href.contains("daydayzhuan.com")){
                    aEle.attr("rel","nofollow");
                }
            }
        }
//        text-indent修改为document.children()下所有节点，不只是P节点，也有可能是div
        Elements childEles = null;
        if(document.select("body") != null && document.select("body").size() > 0){
            childEles = document.select("body").get(0).children();
        }else{
            childEles = document.children();
        }
        for (Element element : childEles) {
            //去除空格
            String newHtml = element.html().replaceAll("&nbsp;", "").trim();
            element.html(newHtml);
            if(element.select("img") == null || element.select("img").size() == 0){
                //增加text-indent
                String style = element.attr("style");
                if(StringUtils.isEmpty(style)){
                    style = "";
                }
                style += ";text-indent:2em;";
                element.attr("style",style);
            }
        }
        return document.html();
    }

    /**
     * 根据文章类型设置封面
     * @param project
     */
    private void setCoverByTypeAndFrom(ProjectDto project) {
        //1、如果是变现反馈、项目进展文章，直接使用第一张图片作为封面。
        //2、如果不是上述项目，且是薅羊毛项目或者首码项目，使用第二张图片作为封面（通常第一张是邀请码）
        Document document = Jsoup.parse(project.getContent());
        Elements elements = document.select("img");
        //是否有jpg/png/jpeg的图片
        List<Element> imgList = elements.stream().filter(e -> {
            String src = e.attr("src");
            if (src.contains(".jpg") || src.contains(".png") || src.contains(".jpeg")) {
                return true;
            } else {
                return false;
            }
        }).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(imgList)){
            elements = null;
        }
        if(elements != null && elements.size() > 0){
            String from = project.getSource();
            if(ProjectFromConstant.PROCESS.equals(from) || ProjectFromConstant.WITHDRAW.equals(from)){
                project.setCover(CommonUtil.deleteOSSImgPre(elements.get(0).attr("src")));
            }else{
                Element imgEle = elements.stream().filter(ele -> {
                    String src = ele.attr("src");
                    return !ImageUtils.isQRCodeInImage(src);
                }).findFirst().orElse(null);

                if(imgEle != null && StrUtil.isNotBlank(imgEle.attr("src"))) {
                    String src = imgEle.attr("src");
                    project.setCover(CommonUtil.deleteOSSImgPre(src));
                }else {
//                    SpiderImageEntity spiderImage = spiderImageService.getSpiderImage();
                    project.setCover("img/redbag.png");
                }
            }
        }else{
            project.setCover("img/redbag.png");
        }
    }

    /**
     * 记录作者提交记录
     * @param createId
     */
    private void commitRecord(Integer createId) {
        Optional<UserEntity> optionalUserEntity = userRepository.findById(createId);
        UserEntity userEntity = optionalUserEntity.get();
        AdminUserDto adminUserDto = userMapper.entityToDto(userEntity);

        List<AdminUserDto> userList = RedisUtils.readList(RedisKeyPrefix.PROJECTCOMMIT);
        if(userList == null){
            userList = new ArrayList<>();
        }
        //是否存在该用户ID，如果存在则移除，再插入到list头
        Iterator<AdminUserDto> iterator = userList.iterator();
        while (iterator.hasNext()){
            AdminUserDto u = iterator.next();
            if(u.getId().intValue() == createId){
                iterator.remove();
            }
        }
        userList.add(0,adminUserDto);

        redisTemplate.opsForValue().set(RedisKeyPrefix.PROJECTCOMMIT,userList.size()>10?new ArrayList<>(userList.subList(0,11)):userList);
    }

    @Override
    public ProjectEntity getProjectById(Integer projectId) {
        Optional<ProjectEntity> optionalProject = projectRepository.findById(projectId);
        if (optionalProject.isPresent()) {
            return optionalProject.get();
        }
        return null;
    }

    @Override
    public void update(ProjectAddRequest project) {
        Optional<ProjectEntity> optionalProject = projectRepository.findById(project.getId());
        if (!optionalProject.isPresent()) {
            throw new RuntimeException("id对应的实体不存在:"+project.getId());
        }
        ProjectEntity entity = optionalProject.get();
        //保存项目
        ProjectEntity projectEntity = projectMapper.addRequestToEntity(project,entity);

        List<Integer> containAppIdList = new ArrayList<>();
        projectEntity.setContent(this.setInvateImage(project.getContent(),project.getTitle()));
        projectEntity.setContent(this.insertApp(projectEntity.getContent(),containAppIdList));
        projectRepository.save(projectEntity);

        //保存project-app关联关系
        List<ProjectAppEntity> projectAppList = projectAppRepository.findByProjectId(projectEntity.getId());
        projectAppRepository.deleteAll(projectAppList);
        if(CollectionUtil.isNotEmpty(containAppIdList)){
            containAppIdList.stream().forEach(appId -> {
                ProjectAppEntity relation = new ProjectAppEntity();
                relation.setProjectId(projectEntity.getId());
                relation.setAppId(appId);
                projectAppRepository.save(relation);
            });
        }

        //删除、重新设置项目-专题关联
        List<ProjectSubjectEntity> projectSubjectList = projectSubjectRepository.findByProjectId(project.getId());
        projectSubjectRepository.deleteAll(projectSubjectList);
        if(CollectionUtil.isNotEmpty(project.getSubjectIdList())){
            project.getSubjectIdList().stream().forEach(subjectId ->{
                ProjectSubjectEntity projectSubject = new ProjectSubjectEntity();
                projectSubject.setProjectId(project.getId());
                projectSubject.setSubjectId(subjectId);
                projectSubjectRepository.save(projectSubject);
            });
        }

        //删除project_type project_label 关联
        List<ProjectLabelEntity> projectLabelList = projectLabelRepository.findByProjectid(project.getId());
        projectLabelList.stream().forEach(e -> projectLabelRepository.delete(e));

        List<ProjectLabelEntity> projectLabelKeyList = new ArrayList<>();

        //关键词保存到label中
        String keyword = project.getKeyword();
        if(!StringUtils.isEmpty(keyword)){
            String[] split = keyword.split(",");
            for (String key : split) {
                LabelEntity existLabel = labelRepository.findByLabelName(key);
                if(existLabel == null){
                    existLabel = new LabelEntity();
                    existLabel.setIsShowTitle(0);
                    existLabel.setLabelName(key);
                    labelRepository.save(existLabel);

                    ProjectLabelEntity projectLabelKey = new ProjectLabelEntity();
                    projectLabelKey.setLabelid(Integer.valueOf(existLabel.getId()));
                    projectLabelKey.setProjectid(project.getId());
                    projectLabelKeyList.add(projectLabelKey);
                }else{
                    ProjectLabelEntity projectLabelKey = new ProjectLabelEntity();
                    projectLabelKey.setLabelid(Integer.valueOf(existLabel.getId()));
                    projectLabelKey.setProjectid(project.getId());
                    projectLabelKeyList.add(projectLabelKey);
                }
            }
        }

        if(CollectionUtils.isNotEmpty(projectLabelKeyList)){
            //批量插入项目_标签表
            projectLabelRepository.saveAll(projectLabelKeyList);
        }

        //删除今日可赚
        redisTemplate.delete(RedisKeyPrefix.PROFIT_TODAY);

        //删除置顶文章
        redisTemplate.delete(RedisKeyPrefix.PROJECT_RECOMMENTED);
    }


    @Override
    public List<ProjectCommentDto> getCommentProjectList() {
        Object obj = redisTemplate.opsForValue().get(RedisKeyPrefix.PROJECT_RECOMMENTED);
        if(obj == null) {
            List<ProjectCommentDto> list = projectRepository.findByCommentedAndOfflineOrderByCreateTimeDesc("1", "0");
            for(ProjectCommentDto project:list){
                boolean today = CommonUtil.isSameDate(new Date(),project.getCreateTime());
                project.setIsToday(today == true ? "1":"0");
                project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"MM-dd"));
            }
            redisTemplate.opsForValue().set(RedisKeyPrefix.PROJECT_RECOMMENTED, list);
            return list;
        }else {
            return (List<ProjectCommentDto>)obj;
        }
    }

    @Override
    public TabelData<ProjectDto> getIndexData(Page page) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity);

        QueryResults<ProjectEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qProjectEntity.createTime.desc())
                .fetchResults();

        List<ProjectDto> list = queryResults.getResults().stream().map(e->projectMapper.entityToDto(e)).collect(Collectors.toList());

        list.stream().forEach(e ->{
            Date currenDate = new Date();
            boolean isCurren = CommonUtil.isSameDate(currenDate,e.getCreateTime());
            if(isCurren){
                //当天
                e.setIsToday("1");
            }else{
                e.setIsToday("0");
            }
        });

        //格式化创建时间、封面
        this.projectHandle(list);

        return new TabelData(list,(int)queryResults.getTotal());
    }

    private void projectHandle(List<ProjectDto> projects) {

        if(projects != null && projects.size()>0){
            for(ProjectDto project:projects){
                if(project.getCreateTime()!=null){
                    project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd"));
                }
                if(!StringUtils.isEmpty(project.getCover())){
                    if(!project.getCover().startsWith("https://") && !project.getCover().startsWith("http://")){
                        project.setCover(ossService.getImgUrl(project.getCover()));
                    }else{
                        project.setCover(CommonUtil.deleteOSSImgSuff(project.getCover()));
                    }
                }
                //如果项目被禁用，则封面改为下架的封面，标题加上已下架提示
                if(ProjectConst.OFFLINE.equals(project.getOffline())){
                    project.setCover("/img/disable.png");
                    project.setTitle("【已下架】"+project.getTitle());
                }
            }
        }
    }

    private void projectHandle2(List<ProjectEntity> projects) {
        if(projects != null && projects.size()>0){
            for(ProjectEntity project:projects){
                if(project.getCreateTime()!=null){
                    project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd"));
                }
                if(!StringUtils.isEmpty(project.getCover())){
                    if(!project.getCover().startsWith("https://") && !project.getCover().startsWith("http://")){
                        project.setCover(CommonUtil.deleteOSSImgSuff(ossService.getImgUrl(project.getCover()))+OSSClientConstants.COVER_WATER_MARK);
                    }else{
                        project.setCover(CommonUtil.deleteOSSImgSuff(project.getCover())+OSSClientConstants.COVER_WATER_MARK);
                    }
                }
                //如果项目被禁用，则封面改为下架的封面，标题加上已下架提示
                if(ProjectConst.OFFLINE.equals(project.getOffline())){
                    project.setCover("/img/disable.png");
                    project.setTitle("【已下架】"+project.getTitle());
                }
            }
        }
    }

    @Override
    public TabelData<ProjectDto> getProjectByTypeIdPage(Page page,Integer typeId,Boolean isTop) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity).where(qProjectEntity.typeObj.id.eq(typeId));

        if(isTop != null && isTop){
            query = query.orderBy(qProjectEntity.commented.desc(),qProjectEntity.sortIndex.desc(),qProjectEntity.createTime.desc());
        }else{
            query = query.orderBy(qProjectEntity.createTime.desc());
        }

        QueryResults<ProjectEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .fetchResults();

        List<ProjectDto> list = queryResults.getResults().stream().map(e->projectMapper.entityToDto(e)).collect(Collectors.toList());
        //格式化创建时间、封面
        this.projectHandle(list);

        return new TabelData(list,(int)queryResults.getTotal());
    }



    @Override
    public List<ProjectDto> getNewProjectList(Integer count) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectDto> query = factory.select(Projections.bean(ProjectDto.class,qProjectEntity.isNofollow,qProjectEntity.id,qProjectEntity.title,qProjectEntity.createTime,qProjectEntity.typeId)).from(qProjectEntity)
                .where(qProjectEntity.offline.eq("0"),qProjectEntity.isHomePage.eq("1"))
                .orderBy(qProjectEntity.createTime.desc())
                .limit(count);
        return query.fetch();
    }

    @Override
    public List<ProjectDto> getNewProjectListPage(int page,int limit) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity)
                .where(qProjectEntity.offline.eq("0"),qProjectEntity.isHomePage.eq("1"))
                .offset(PageRequest.of(page - 1, limit).getOffset()).limit(limit)
                .orderBy(qProjectEntity.createTime.desc());

        List<ProjectEntity> list = query.fetch();
        list.stream().forEach(project->{
            boolean today = CommonUtil.isSameDate(new Date(),project.getCreateTime());
            project.setIsToday(today == true ? "1":"0");
            project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"MM-dd"));
        });
        return list.stream().map(e->projectMapper.entityToDto(e)).collect(Collectors.toList());
    }



    @Override
    public List<ProjectDto> getCommentProjectList2() {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity)
                .where(qProjectEntity.offline.eq("0"),qProjectEntity.commented.eq("1"))
                .orderBy(qProjectEntity.createTime.desc());

        List<ProjectEntity> projectList = query.fetch();
        for(ProjectEntity project:projectList){
            boolean today = CommonUtil.isSameDate(new Date(),project.getCreateTime());
            project.setIsToday(today == true ? "1":"0");
            project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"MM-dd"));
        }
        return projectList.stream().map(e -> projectMapper.entityToDto(e)).collect(Collectors.toList());
    }

    @Override
    public ProjectDto getProjectById_forAndroid(Integer projectId) {
        Optional<ProjectEntity> optionalProject = projectRepository.findById(projectId);
        if(optionalProject.isPresent()){
            ProjectEntity projectEntity = optionalProject.get();
            projectEntity.setShowCreateTime(CommonUtil.getDateByFormat(projectEntity.getCreateTime(),"MM-dd"));
            return projectMapper.entityToDto(projectEntity);
        }
        return null;
    }

    @Override
    public TabelData<ProjectDto> getSerchPage(Page page, String key) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity);
        if(StrUtil.isNotBlank(key)){
            query = query.where(qProjectEntity.title.like("%"+key+"%"));
        }

        QueryResults<ProjectEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qProjectEntity.createTime.desc())
                .fetchResults();

        List<ProjectDto> list = queryResults.getResults().stream().map(e->projectMapper.entityToDto(e)).collect(Collectors.toList());

        //格式化创建时间、封面
        this.projectHandle(list);

        return new TabelData(list,(int)queryResults.getTotal());
    }

    @Override
    public TabelData<ProjectDto> getProjectByKeyIdPage(Page page, String keyId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity);

        List<ProjectLabelEntity> projectLabelList = projectLabelRepository.findByLabelid(Integer.valueOf(keyId));
        List<Integer> projectIdList = projectLabelList.stream().map(e -> e.getProjectid()).collect(Collectors.toList());

        query = query.where(qProjectEntity.id.in(projectIdList));

        QueryResults<ProjectEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qProjectEntity.createTime.desc())
                .fetchResults();

        List<ProjectDto> list = queryResults.getResults().stream().map(e->projectMapper.entityToDto(e)).collect(Collectors.toList());
        //格式化创建时间、封面
        this.projectHandle(list);

        return new TabelData(list,(int)queryResults.getTotal());
    }

    @Override
    public ProjectEndEntity getProjectEndRandom() {
        return projectEndRepository.selectOne();
    }

    @Override
    public ProjectEntity getLastProjectByLabelId(Integer labelId) {
        QProjectLabelEntity qProjectLabelEntity = QProjectLabelEntity.projectLabelEntity;
        List<ProjectLabelEntity> projectLabelEntityList = factory.selectFrom(qProjectLabelEntity).where(qProjectLabelEntity.labelid.eq(labelId))
                .orderBy(qProjectLabelEntity.projectid.desc())
                .limit(1)
                .fetch();

        if(CollectionUtil.isEmpty(projectLabelEntityList)){
            return null;
        }
        ProjectLabelEntity projectLabelEntity = projectLabelEntityList.get(0);
        Optional<ProjectEntity> optionalProject = projectRepository.findById(projectLabelEntity.getProjectid());
        if(optionalProject.isPresent()){
            return optionalProject.get();
        }
        return null;
    }

    @Override
    public List<ProjectDto> getProjectListByTypeId(List<Integer> typeIdList,Map<Integer,TypeDto> typeMap) {
        List<ProjectDto> res = new ArrayList<>();
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        for (Integer typeId : typeIdList) {
            List<ProjectDto> list = factory.select(Projections.bean(ProjectDto.class,qProjectEntity.id,qProjectEntity.createTime,qProjectEntity.isNofollow,qProjectEntity.title)).from(qProjectEntity).where(qProjectEntity.offline.eq("0"), qProjectEntity.typeObj.id.eq(typeId))
                    .orderBy(qProjectEntity.createTime.desc())
                    .limit(10).fetch();
            TypeDto typeDto = typeMap.get(typeId);
            list.stream().forEach(dto -> dto.setTypeObj(typeDto));
            res.addAll(list);
        }
        return res;
    }

    @Override
    public List<ProjectDto> getYangmaoListPage(Integer page, Integer limit,Integer typeId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        List<ProjectEntity> list = factory.selectFrom(qProjectEntity).where(qProjectEntity.offline.eq("0"), qProjectEntity.typeObj.id.eq(typeId))
                .offset(PageRequest.of(page - 1, limit).getOffset()).limit(limit)
                .orderBy(qProjectEntity.createTime.desc()).fetch();

        for(ProjectEntity project:list){
            boolean today = CommonUtil.in24Hour(new Date(),project.getCreateTime());
            project.setIsToday(today == true ? "1":"0");
            project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"MM-dd"));
            project.setCover(ossService.getImgUrl(project.getCover()));

        }
        return list.stream().map(e-> {
            ProjectDto dto = projectMapper.entityToDto(e);
            dto.setTimeAgo(TimeAgoUtils.format(CommonUtil.getDateByFormat(e.getCreateTime(),"yyyy-MM-dd HH:mm:ss")));
            return dto;
        }).collect(Collectors.toList());
    }


    @Override
    public TabelData<ProjectEntity> getProjectByUserIdPage(Page page, Integer uid) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        QueryResults<ProjectEntity> queryResults = factory.selectFrom(qProjectEntity).where(qProjectEntity.offline.eq("0"), qProjectEntity.createId.eq(uid))
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qProjectEntity.createTime.desc()).fetchResults();

        List<ProjectEntity> list = queryResults.getResults();

        //格式化创建时间、封面
        this.projectHandle2(list);

        return new TabelData(list,(int)queryResults.getTotal());
    }

    @Override
    public List<ProcessProjectDto> getWithDrawListHome(Integer projectId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProcessProjectDto> query = factory.select(Projections.bean(ProcessProjectDto.class,qProjectEntity.id,qProjectEntity.title,qProjectEntity.cover)).from(qProjectEntity).where(qProjectEntity.source.eq("withdraw"));

        if(projectId != null){
            query = query.where(qProjectEntity.projectId.eq(projectId));
        }

        List<ProcessProjectDto> list = query.orderBy(qProjectEntity.createTime.desc()).limit(8).fetch();
        if(!org.springframework.util.CollectionUtils.isEmpty(list)){
            for (ProcessProjectDto project : list) {
                String cover = project.getCover();
                if(!cover.startsWith("http")){
                    project.setCover(ossService.getImgUrl(project.getCover()));
                }
            }
        }
        return list;
    }

    @Override
    public TabelData<ProjectEntity> getWithDrawListPage(Page page,Integer projectId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity).where(qProjectEntity.source.eq("withdraw"));

        if(projectId != null){
            query = query.where(qProjectEntity.projectId.eq(projectId));
        }

        QueryResults<ProjectEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qProjectEntity.createTime.desc())
                .fetchResults();

        List<ProjectEntity> list = queryResults.getResults();

        //格式化创建时间、封面
        this.projectHandle2(list);

        return new TabelData(list,(int)queryResults.getTotal());
    }

    @Override
    public TabelData<ProjectDto> getTemProjectList() {
        List<ProjectDto> temProjectList = RedisUtils.readList(RedisKeyPrefix.PROJECTTEMLIST);
        TabelData<ProjectDto> tabelData = new TabelData<>();
        if(temProjectList != null){
            for (ProjectDto project : temProjectList) {
                if(project.getCreateTime()!=null){
                    project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd"));
                }
                TypeDto type = project.getTypeObj();
                project.setTypes(type.getTypeName());
            }
            tabelData.setCount(temProjectList.size());
            tabelData.setData(temProjectList);
        }

        return tabelData;
    }

    @Override
    public List<ProjectEntity> getProjectListByNoFollow() {
        return projectRepository.findByIsNofollowOrderByCreateTimeDesc(0);
    }

    @Override
    public List<ProjectDto> findByAppId(Integer appId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        QProjectAppEntity qProjectAppEntity = QProjectAppEntity.projectAppEntity;
        return factory.select(Projections.bean(ProjectDto.class,qProjectEntity.id,qProjectEntity.title,qProjectEntity.createTime))
                .from(qProjectEntity)
                .leftJoin(qProjectAppEntity)
                .on(qProjectEntity.id.eq(qProjectAppEntity.projectId))
                .where(qProjectEntity.offline.eq("0"))
                .where(qProjectAppEntity.appId.eq(appId))
                .orderBy(qProjectEntity.id.desc())
                .limit(10)
                .fetch();
    }

    @Override
    public ProjectDto handleApp(ProjectDto dto) {
        String content = dto.getContent();
        Document document = Jsoup.parse(content);
        Elements elements = document.select("div.relation_div");
        for (Element element : elements) {
            String appIdStr = element.attr("data-id");
            if(StrUtil.isBlank(appIdStr)){
                continue;
            }
            String appId = appIdStr.replaceAll("app-", "");
            Optional<AppEntity> optionApp = appRepository.findById(Integer.valueOf(appId));
            if (!optionApp.isPresent()) {
                continue;
            }
            AppEntity appEntity = optionApp.get();
            element.tagName("a");
            element.text(appEntity.getTitle()+":点击下载app");
            element.attr("href","https://www.daydayzhuan.com/app/"+appId);
        }
        dto.setContent(document.html());
        return dto;
    }

    @Override
    public BigDecimal getProfitToday() {
        Object profit = redisTemplate.opsForValue().get(RedisKeyPrefix.PROFIT_TODAY);
        if(profit != null){
            return (BigDecimal) profit;
        }
        String dateStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        String begin = dateStr + " 00:00:00";
        String end = dateStr + " 23:59:59";
        profit = projectRepository.totalProfitToday(begin,end);
        redisTemplate.opsForValue().set(RedisKeyPrefix.PROFIT_TODAY,profit);
        return (BigDecimal)profit;
    }

    @Override
    public TabelData<ProjectDto> getProjectByTypeIdAndLabelIdPage(Page page, Integer typeId, Boolean isTop, Integer labelId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity).where(qProjectEntity.typeObj.id.eq(typeId));

        if(labelId != null) {
            QProjectLabelEntity qProjectLabel = QProjectLabelEntity.projectLabelEntity;
            query.leftJoin(qProjectLabel).on(qProjectLabel.labelid.eq(labelId) ,qProjectEntity.id.eq(qProjectLabel.projectid)).where(qProjectLabel.id.isNotNull());
        }

        if(isTop != null && isTop){
            query = query.orderBy(qProjectEntity.commented.desc(),qProjectEntity.sortIndex.desc(),qProjectEntity.createTime.desc());
        }else{
            query = query.orderBy(qProjectEntity.createTime.desc());
        }

        QueryResults<ProjectEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .fetchResults();

        List<ProjectDto> list = queryResults.getResults().stream().map(e->projectMapper.entityToDto(e)).collect(Collectors.toList());
        //格式化创建时间、封面
        this.projectHandle(list);

        return new TabelData(list,(int)queryResults.getTotal());
    }

    @Override
    public List<TypeDto> getTypeList(Integer projectTypeId) {
        List<TypeDto> typeList = new ArrayList<>();
        Iterator<TypeEntity> iterator = typeRepository.findAll().iterator();
        while (iterator.hasNext()) {
            TypeEntity entity = iterator.next();
            typeList.add(typeMapper.entityToDto(entity));
        }
        //标记该项目已选择的标签和类型
        if(projectTypeId != null) {
            for(TypeDto t:typeList){
                if(projectTypeId == t.getId().intValue()){
                    t.setSelected(true);
                }
            }
        }
        return typeList;
    }

    @Override
    public List<LabelDto> getTopLables() {
        List<LabelEntity> topLabelEntitys = labelRepository.findByType_IdAndIsTop(1, true);
        List<LabelDto> topLables = topLabelEntitys.stream().map(e -> labelMapper.entityToDto(e)).collect(Collectors.toList());
        return topLables;
    }

    @Override
    public R updateProfit() {
        logger.info("开始更新profit");
        PageRequest page = PageRequest.of(0, 100, Sort.Direction.DESC, "id");
        org.springframework.data.domain.Page<ProjectEntity> projectPage = projectRepository.findByProfitIsNull(page);
        int index = 1;
        while (projectPage.hasContent()) {
            List<ProjectEntity> list = projectPage.getContent();
            List<ProjectEntity> updateList = new ArrayList<>();
            for (ProjectEntity project : list) {
                String regex = "\\d+\\.\\d+|(\\d+)";
                String profit = ReUtil.getGroup0(regex, project.getTitle());
                if(project.getTitle().contains(profit+"元") || project.getTitle().contains(profit+"以上")) {
                    logger.info("更新文章的profit，文章id：{}，profit:{}", project.getId(), profit);
                    project.setProfit(new BigDecimal(profit));
                    updateList.add(project);
                }
            }
            if(CollUtil.isNotEmpty(updateList)) {
                projectRepository.saveAll(updateList);
            }

            projectPage = projectRepository.findAll(PageRequest.of(index++, 100, Sort.Direction.DESC, "id"));
        }
        logger.info("更新profit结束");
        return R.ok("success");
    }

    @Override
    public Integer getYangmaoArticleCount() {
        String key = RedisKeyPrefix.Yangmao_ARTICLE_COUNT;
        Object articleCountObj = redisTemplate.opsForValue().get(key);
        if(articleCountObj == null){
            Integer count = projectRepository.findYangmaoArticleCount();
            redisTemplate.opsForValue().set(key,count==null?0:count);
            redisTemplate.expire(key,1, TimeUnit.DAYS);

            return count==null?0:count;
        }else{
            return (Integer)articleCountObj;
        }
    }

    @Override
    public BigDecimal getAllProfit() {
        String key = RedisKeyPrefix.All_Profit;
        Object allProfitObj = redisTemplate.opsForValue().get(key);
        if(allProfitObj == null){
            BigDecimal profits = projectRepository.findAllProfit();
            redisTemplate.opsForValue().set(key,profits==null?BigDecimal.ZERO:profits);
            redisTemplate.expire(key,1, TimeUnit.DAYS);

            return profits==null?BigDecimal.ZERO:profits;
        }else{
            return (BigDecimal) allProfitObj;
        }
    }


    @Override
    public List<ProjectDto> getRankProjectListByMonth(Integer typeId) {
        Date date = new Date();
        DateTime monthAgoDate = DateUtil.offsetDay(date, -30);

        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        return factory.select(Projections.bean(ProjectDto.class,qProjectEntity.id,qProjectEntity.title,qProjectEntity.createTime)).from(qProjectEntity)
                .where(qProjectEntity.offline.eq("0"),qProjectEntity.typeObj.id.eq(typeId),qProjectEntity.createTime.goe(monthAgoDate),qProjectEntity.createTime.loe(date))
                .orderBy(qProjectEntity.readMount.desc())
                .limit(10)
                .fetch();
    }


    /**
     * 获取最新更新的10片（不包含网赚闲谈）
     * @param count
     * @return
     */
    public List<ProjectEntity> getTopProject(int count) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;

        return factory.selectFrom(qProjectEntity)
                .where(qProjectEntity.typeObj.id.ne(10),qProjectEntity.offline.eq("0"))
                .orderBy(qProjectEntity.createTime.desc())
                .limit(count)
                .fetch();
    }

    public List<ProjectEntity> getLikeLabelProjectList(Integer projectId,Integer typeId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        return factory.selectFrom(qProjectEntity).where(qProjectEntity.offline.eq("0"),qProjectEntity.id.ne(projectId))
                .orderBy(qProjectEntity.createTime.desc())
                .limit(10).fetch();
//        return projectRepository.getLikeLabelProjectList(projectId,typeId);
    }

    public List<ProjectNextPreDto> getNextAndPre(Integer projectId) {
        List<Map<String, Object>> nextAndPre = projectRepository.getNextAndPre(projectId);
        List<ProjectNextPreDto> result = new ArrayList<>();
        return nextAndPre.stream().map(map -> {
            ProjectNextPreDto dto = new ProjectNextPreDto();
            dto.setId(Integer.valueOf(map.get("id").toString()));
            dto.setTitle(map.get("title").toString());
            return dto;
        }).collect(Collectors.toList());
    }

    public List<ProcessProjectDto> getProcessById(Integer id) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        return factory.select(Projections.bean(ProcessProjectDto.class,qProjectEntity.id,qProjectEntity.title)).from(qProjectEntity)
                .where(qProjectEntity.source.eq("process"),qProjectEntity.projectId.eq(id))
                .orderBy(qProjectEntity.createTime.desc())
                .limit(3)
                .fetch();
    }

    public List<ProjectDto> findBySubjectId(Integer subjectId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        SubjectEntity subjectEntity = new SubjectEntity();
        subjectEntity.setId(subjectId);
        return factory.select(Projections.bean(ProjectDto.class, qProjectEntity.id, qProjectEntity.title)).from(qProjectEntity)
                .where(qProjectEntity.subjectList.contains(subjectEntity), qProjectEntity.offline.eq("0"))
                .orderBy(qProjectEntity.readMount.desc())
                .limit(6)
                .fetch();
    }

    public List<ProjectDto> findNewProjectBySubjectId(Integer subjectId) {
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        SubjectEntity subject = new SubjectEntity();
        subject.setId(subjectId);
        return factory.select(Projections.bean(ProjectDto.class, qProjectEntity.id, qProjectEntity.title)).from(qProjectEntity)
                .where(qProjectEntity.subjectList.contains(subject), qProjectEntity.offline.eq("0"))
                .orderBy(qProjectEntity.id.desc())
                .limit(6)
                .fetch();
    }

    public void updateCount(Integer projectId) {
        projectRepository.updateCount(projectId);
    }

    public List<ProjectDto> getCurrentProjectList() {
        String dateStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        String begin = dateStr + " 00:00:00";
        String end = dateStr + " 23:59:59";
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        SubjectEntity subject = new SubjectEntity();
        return factory.select(Projections.bean(ProjectDto.class, qProjectEntity.id, qProjectEntity.projectName)).from(qProjectEntity)
                .where(qProjectEntity.createTime.goe(DateUtil.parse(begin)), qProjectEntity.createTime.loe(DateUtil.parse(end)))
                .fetch();
    }

    public void create(String title,String keyword,Integer adminId,String content,String isTemp) {
        ProjectDto dto = new ProjectDto();
        dto.setCommented("0");
        dto.setContent(content);
        dto.setCover(null);
        dto.setIsHomePage("1");
        dto.setIsNofollow(0);
        dto.setIsTemp(isTemp);
        dto.setKeyword(keyword);
        dto.setSummary(content.length()>108?content.substring(0,107)+"......":content);
        dto.setTitle(title);
        dto.setTypes("3");
        dto.setType(ProjectConst.NORMAL_PROJECT); //标志为普通项目
        dto.setCreateTime(new Date()); //设置创建时间
        dto.setReadMount(0);//阅读数量
        dto.setCommentMount(0);//评论数量
        dto.setCreateId(adminId);//创建人ID
        dto.setOffline(ProjectConst.UNOFFLINE); //默认未下架
        dto.setUpdateTime(new Date());

        this.save(dto);
    }

    @Async
    public void like(Integer id,HttpServletRequest request) {
        ProjectEntity project = projectRepository.findById(id).orElse(null);
        if(project != null){
            Integer count = project.getLikes()==null?0:project.getLikes();
            project.setLikes(++count);
            projectRepository.save(project);
            this.saveProjectDipLikeEntity(project.getId(), ProjectLikeDipEnum.LIKE,IPUtil.getIpAddr(request));
        }
    }

    @Async
    public void dip(Integer id,HttpServletRequest request) {
        ProjectEntity project = projectRepository.findById(id).orElse(null);
        if(project != null){
            Integer count = project.getDips()==null?0:project.getDips();
            project.setDips(++count);
            projectRepository.save(project);
            this.saveProjectDipLikeEntity(project.getId(),ProjectLikeDipEnum.DIP,IPUtil.getIpAddr(request));
        }
    }

    private void saveProjectDipLikeEntity(Integer id, ProjectLikeDipEnum type,String ip) {
        ProjectLikeDipEntity e = new ProjectLikeDipEntity();
        e.setProjectId(id);
        e.setCreateTime(new Date());
        e.setType(type);
        e.setIp(ip);
        projectLikeDipRepository.save(e);
    }
}
